﻿#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author  : hu_cl
# @Contact : 760730895@qq.com 
# @Date    : 2020/7/27 18:06
# @File    : start_bkup.py
import config
import time
import base64
import pymysql
import datetime
from apscheduler.schedulers.background import BackgroundScheduler
from data_file_backups import BackupFile
from mysql_backups import BackupMysql
from oracle_backups import BackupOracle
from pgsql_backups import BackupPgsql


class MysqlDb(object):
    # 对存储config配置表和log配置表的操作
    def __init__(self, database_name):
        self.mysql_db = pymysql.connect(**database_name)
        self.mysql_cursor = self.mysql_db.cursor()
        self.insert_data_list = []

    def get_data_mysql(self, db_sql):
        # 获取表数据
        self.mysql_cursor.execute(db_sql, args=None)
        field_list = []
        for fields in self.mysql_cursor.description:
            field_list.append(fields[0])
        for result in self.mysql_cursor.fetchall():
            result = list(result)
            item = dict(zip(field_list, result))
            yield item

    def insert_data_mysql(self, table, item):
        keys, vals = list(item.keys()), list(item.values())
        field = ','.join(keys)
        val = ','.join(['%s'] * len(item))
        insert_sql = "replace into " + table + " (" + field + ") VALUES (" + val + ")"
        self.insert_data_list.append(vals)
        if len(self.insert_data_list) == 1:
            try:
                self.mysql_cursor.executemany(insert_sql, self.insert_data_list)
            except Exception as e:
                print(f'插入数据出错, {e}')
            else:
                self.mysql_db.commit()
                self.insert_data_list.clear()


def file_process(dirt_data):
    # 文件备份调用功能
    print('正在进行%s备份，请稍等....' % dirt_data['task_name'])
    file_main_db = MysqlDb(config.MYSQL_CONFIG)
    item = {}
    try:
        item['task_id'] = dirt_data['task_id']
        item['start_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        backfield = BackupFile(dirt_data['source_host'], dirt_data['source_username'], dirt_data['source_pwd'],
                               dirt_data['source_port'])
        filename = backfield.tar_files(backfield.ssh_client, dirt_data['source_file'], dirt_data['source_dir'])
        backfield.download_file(backfield.ssh_client, dirt_data['source_dir'], dirt_data['target_dir'], filename)
        backfield.remove_file(backfield.ssh_client, dirt_data['source_dir'], filename)
        backfield.ssh_client.close()
        item['end_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    except Exception as err_num:
        item['end_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        item['status'], item['remark'] = 2, str(err_num)
    else:
        item['status'], item['remark'] = 1, None
    item['task_name'] = dirt_data['task_name']
    file_main_db.insert_data_mysql('tc_sync_log', item)
    file_main_db.mysql_db.close()


def mysql_process(dirt_data):
    # mysql数据库备份调用功能
    print('正在进行%s备份开始请稍等...' % dirt_data['task_name'])
    mysql_main_db = MysqlDb(config.MYSQL_CONFIG)
    item = {}
    dirt_data['db_pwd'] = base64.b64decode(dirt_data['db_pwd']).decode('utf8')
    try:
        item['task_id'] = dirt_data['task_id']
        item['start_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        backcombs = BackupMysql(dirt_data['source_host'], dirt_data['source_port'], dirt_data['source_username'],
                                dirt_data['source_pwd'], dirt_data['source_dir'], dirt_data['db_name'])
        backcombs.backup_cmd(backcombs.ssh_client, dirt_data['db_name'], dirt_data['db_username'], dirt_data['db_pwd'])
        backcombs.zip_files(backcombs.ssh_client)
        backcombs.download(backcombs.ssh_client, dirt_data['target_dir'])
        backcombs.remove_file(backcombs.ssh_client)
        backcombs.ssh_client.close()
        item['end_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    except Exception as err_num:
        item['end_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        item['status'], item['remark'] = 2, str(err_num)
    else:
        item['status'], item['remark'] = 1, None
    item['task_name'] = dirt_data['task_name']
    mysql_main_db.insert_data_mysql('tc_sync_log', item)
    mysql_main_db.mysql_db.close()


def oracle_process(datum):
    # oracle数据库备份调用功能
    print('正在进行%s备份开始请稍等....' % datum['task_name'])
    oracle_main_db = MysqlDb(config.MYSQL_CONFIG)
    item = {}
    datum['db_pwd'] = base64.b64decode(datum['db_pwd']).decode('utf8')
    try:
        item['task_id'] = datum['task_id']
        item['start_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        backache = BackupOracle(datum['source_host'], datum['source_port'], datum['source_username'],
                                datum['source_pwd'], datum['source_dir'], datum['db_name'])
        backache.backup_cmd(backache.ssh_client, datum['db_username'], datum['db_pwd'], datum['db_name'])
        backache.zip_files(backache.ssh_client)
        backache.download(backache.ssh_client, datum['target_dir'])
        backache.remove_file(backache.ssh_client)
        backache.ssh_client.close()
        item['end_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    except Exception as err_num:
        item['end_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        item['status'], item['remark'] = 2, str(err_num)
    else:
        item['status'], item['remark'] = 1, None
    item['task_name'] = datum['task_name']
    oracle_main_db.insert_data_mysql('tc_sync_log', item)
    oracle_main_db.mysql_db.close()


def pgsql_process(datum):
    # pgsql数据库备份调用功能
    print('正在进行%s备份开始请稍等....' % datum['task_name'])
    pgsql_main_db = MysqlDb(config.MYSQL_CONFIG)
    item = {}
    datum['db_pwd'] = base64.b64decode(datum['db_pwd']).decode('utf8')
    try:
        item['task_id'] = datum['task_id']
        item['start_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        backache = BackupPgsql(datum['source_host'], datum['source_port'], datum['source_username'],
                               datum['source_pwd'], datum['source_dir'], datum['db_name'])
        backache.pgsql_backup_cmd(backache.ssh_client, datum['db_name'], datum['db_username'], datum['db_pwd'])
        backache.pgsql_zip_files(backache.ssh_client)
        backache.pgsql_download(backache.ssh_client, datum['target_dir'])
        backache.pgsql_remove_file(backache.ssh_client)
        backache.ssh_client.close()
        item['end_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    except Exception as err_num:
        item['end_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        item['status'], item['remark'] = 2, str(err_num)
    else:
        item['status'], item['remark'] = 1, None
    item['task_name'] = datum['task_name']
    pgsql_main_db.insert_data_mysql('tc_sync_log', item)
    pgsql_main_db.mysql_db.close()


def timed_sequence(items):
    items['task_id'] = items['task_id']
    items['source_pwd'] = base64.b64decode(items['source_pwd']).decode('utf8')
    items['target_pwd'] = base64.b64decode(items['target_pwd']).decode('utf8')
    if items['task_type'] is 1:
        # 处理文件备份
        if items['cycle_type'] is 1:
            file_process(items)
            scheduler.add_job(file_process, 'interval', days=1, args=[items])
        elif items['cycle_type'] is 2:
            file_process(items)
            scheduler.add_job(file_process, 'interval', days=7, args=[items])
    elif items['task_type'] is 2:
        # 处理mysql数据库备份
        if items['cycle_type'] is 1:
            mysql_process(items)
            scheduler.add_job(mysql_process, 'interval', days=1, args=[items])
        elif items['cycle_type'] is 2:
            mysql_process(items)
            scheduler.add_job(mysql_process, 'interval', days=7, args=[items])
    elif items['task_type'] is 3:
        # 处理oracle数据库备份
        if items['cycle_type'] is 1:
            oracle_process(items)
            scheduler.add_job(oracle_process, 'interval', days=1, args=[items])
        elif items['cycle_type'] is 2:
            oracle_process(items)
            scheduler.add_job(oracle_process, 'interval', days=7, args=[items])
    elif items['task_type'] is 4:
        # pgsql数据库定时任务部分
        if items['cycle_type'] is 1:
            pgsql_process(items)
            scheduler.add_job(pgsql_process, 'interval', days=1, args=[items])
        elif items['cycle_type'] is 2:
            pgsql_process(items)
            scheduler.add_job(pgsql_process, 'interval', days=7, args=[items])


if __name__ == '__main__':
    # BackgroundScheduler() 默认10个线程
    scheduler = BackgroundScheduler(
        {
            'apscheduler.executors.default': {
                'class': 'apscheduler.executors.pool:ThreadPoolExecutor',
                'max_workers': '57'
            },
            'apscheduler.job_defaults.coalesce': 'false',
            'apscheduler.job_defaults.max_instances': '3',
        }
    )
    main_db = MysqlDb(config.MYSQL_CONFIG)
    sql = 'select * from {}.tc_sync_config1'.format(config.MYSQL_CONFIG['db'])
    for data in main_db.get_data_mysql(sql):
        if data['status'] is 1:
            hourtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            nowtime = '{} {}'.format(str(datetime.date.today()), str(data['start_time']))
            nowtime = datetime.datetime.strptime(nowtime, '%Y-%m-%d %H:%M:%S')
            if data['start_time'].__lt__(hourtime):
                nowtime = nowtime + datetime.timedelta(days=1)
            print(data['task_id'], data['start_time'], hourtime, nowtime)
            scheduler.add_job(timed_sequence, args=[data])
            # scheduler.add_job(timed_sequence, 'date', run_date=nowtime, args=[data])
        else:
            pass
    scheduler.start()
    main_db.mysql_db.close()

    try:
        print('程序正在扫描任务....')
        while True:
            time.sleep(600)  # 其他任务是独立的线程执行
            print('现在时间为 %s' % datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    except (KeyboardInterrupt, SystemExit):
        scheduler.shutdown()
        print('Exit The Job!')
